﻿using System;
using ReactiveGraph.Core;
using ReactiveGraph.Extensions.Rules.Core;

namespace ReactiveGraph.Extensions.Rules.Event
{
    public class Rule: RuleBase<NodeEvent> , IEventRuleDeclaration, IEventRuleNodeAction
    {
        public static IEventRuleDeclaration Declare()
        {
            return new Rule();
        }

        IEventRuleAction IEventRuleDeclaration.PropertyChanged(IProperty property)
        {
            return (IEventRuleAction) (this as IEventRuleDeclaration)
                                          .On(e => e.Type == EventType.PropertyChange);
        }

        IEventRuleNodeAction IEventRuleDeclaration.DescendantAdded()
        {
            return (IEventRuleNodeAction)(this as IEventRuleDeclaration)
                                             .On(e => e.Type == EventType.DescendantAdded);
        }

        IEventRuleNodeAction IEventRuleDeclaration.DescendantRemoved()
        {
            return (IEventRuleNodeAction)(this as IEventRuleDeclaration)
                                             .On(e => e.Type == EventType.DescendantRemoved);
        }

        IEventRuleNodeAction IEventRuleDeclaration.ChildAdded(IReactiveNode parent)
        {
            return (IEventRuleNodeAction)(this as IEventRuleDeclaration)
                                             .On(e => e.Type == EventType.DescendantAdded && e.Source.ParentNode == parent);
        }

        IEventRuleNodeAction IEventRuleDeclaration.ChildRemoved(IReactiveNode parent)
        {
            return (IEventRuleNodeAction)(this as IEventRuleDeclaration)
                                             .On(e => e.Type == EventType.DescendantRemoved && e.Source.ParentNode == parent);
        }

        IDeclared<NodeEvent> IEventRuleAction.SetProperty(IProperty destination, object value)
        {
            return (this as IEventRuleAction).Action(e => destination.Value = value);
        }

        IDeclared<NodeEvent> IEventRuleAction.SetProperty(IProperty destination, Func<object> value)
        {
            return (this as IEventRuleAction).Action(e => destination.Value = value());
        }

        IDeclared<NodeEvent> IEventRuleNodeAction.With(Action<IReactiveNode> action)
        {
            return (this as IEventRuleAction).Action(e => action(e.Source.Node));
        }

     
    }
}